<!doctype html>
<html lang="en">
	<head>
		<title>three.js webgl - geometries</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: Monospace;
				background-color: #000;
				margin: 0px;
				overflow: hidden;
			}
		</style>
	</head>
	<body>

		<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>		
  	</body>
		<!-- main library - equivalent to glut -->
		<script type='text/javascript' src="js/Three.js"></script>
		<!-- detect if browser supprts WebGL, otherwise use HTML5 Canvas -->
		<script type='text/javascript' src="js/Detector.js"></script>
		<!-- How many frames per second? -->
		<script type='text/javascript' src="js/Stats.js"></script>
		<script>
/*

Parametric Surfaces Geometry
@author zz85

inspired by http://prideout.net/blog/?p=44

*/

THREE.SurfaceGeometry = function(slices, stacks, func) {
  
  THREE.Geometry.call( this );
  
  var verts = this.vertices, faces = this.faces;
  var pi = Math.PI;
  
  var i, il, theta, j, phi, p;
  
  for (i=0; i<=slices; i++) {
    theta = i * pi / slices;
    
    for (j=0;j<stacks;j++) {
      phi = j * 2 * pi / stacks;
      
      p = func(theta, phi);
      verts.push( new THREE.Vertex(p) );
      
    }
  }
  
  var v = 0, next;
  
  for (i=0;i<slices;i++) {
    for (j=0;j<stacks;j++) {
      next = (j + 1) % stacks;
      faces.push( new THREE.Face3( v + j, v + next, v + j + stacks ) );
      faces.push( new THREE.Face3( v + next, v + next + stacks, v + j + stacks ) );
      
    }
    v += stacks;
  }
  
  
  this.computeCentroids();
  this.computeFaceNormals();
  this.computeVertexNormals();

};

THREE.SurfaceGeometry.prototype = new THREE.Geometry();
THREE.SurfaceGeometry.prototype.constructor = THREE.SurfaceGeometry;

var sin = Math.sin, cos = Math.cos, pi = Math.PI;

function sphere(u, v) {

    var x = sin(u) * cos(v);
    var y = cos(u);
    var z = -sin(u) * sin(v);

    return new THREE.Vector3(x, y, z);
}

function klein(u, v) {
    u = u * 2;
    var x, y, z;
    if (u < pi) {
        x = 3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(u) * cos(v);
        z = -8 * sin(u) - 2 * (1 - cos(u) / 2) * sin(u) * cos(v);
    } else {
        x = 3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(v + pi);
        z = -8 * sin(u);
    }
  
    y = -2 * (1 - cos(u) / 2) * sin(v);
    
    return new THREE.Vector3(x, y, z);
}

if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

var container, stats;

var camera, scene, renderer;

init();
animate();

function init() {

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
    camera.position.y = 400;
    scene.add( camera );

    var light, object, materials;

    scene.add( new THREE.AmbientLight( 0x404040 ) );

    light = new THREE.DirectionalLight( 0xffffff );
    light.position.set( 0, 0, 1 );
    scene.add( light );

    materials = [
       // new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' ) } ),
        new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1 } )
    ];

    object = THREE.SceneUtils.createMultiMaterialObject( new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ), materials );
    object.position.set( -200, 0, 400 );
    scene.add( object );

    object = THREE.SceneUtils.createMultiMaterialObject( new THREE.SurfaceGeometry( 32, 32, sphere ), materials );
    object.children[ 0 ].doubleSided = true;
    object.position.set( 500, 0, 0 );
    object.scale.multiplyScalar(100);
    scene.add( object );

    object = THREE.SceneUtils.createMultiMaterialObject( new THREE.SurfaceGeometry( 32, 32, klein ), materials );
    object.children[ 0 ].doubleSided = true;
    object.position.set( -50, 0, 0 );
    object.scale.multiplyScalar(20);
    scene.add( object );  
  
  
    object = new THREE.AxisHelper();
    object.position.set( 200, 0, -200 );
    object.scale.x = object.scale.y = object.scale.z = 0.5;
    scene.add( object );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );

    container.appendChild( renderer.domElement );

    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0px';
    container.appendChild( stats.domElement );

}

//

function animate() {

    requestAnimationFrame( animate );

    render();
    stats.update();

}

function render() {

	if(cube.animate){
	    var timer = Date.now() * 0.0001;

	    camera.position.x = Math.cos( timer ) * 800;
	    camera.position.z = Math.sin( timer ) * 800;

	    camera.lookAt( scene.position );

	    for ( var i = 0, l = scene.children.length; i < l; i ++ ) {

	        var object = scene.children[ i ];

	        object.rotation.x += 0.01;
	        object.rotation.y += 0.005;
	    }
	}

    renderer.render( scene, camera );

}
		</script>
</html>